From Murillo Fernandes Bernardes <mfb@br.ibm.com>:
authoremellor@leeni.uk.xensource.com <emellor@leeni.uk.xensource.com>
Mon, 31 Oct 2005 16:10:57 +0000 (17:10 +0100)
committeremellor@leeni.uk.xensource.com <emellor@leeni.uk.xensource.com>
Mon, 31 Oct 2005 16:10:57 +0000 (17:10 +0100)
The problem is: There is no mechanism to detect block device setup failure

Network devices have the same problem, and are fixed with this too.

I handling this problem in the way suggested by aliguori:
- hotplug scripts write a "hotplug-status" node on store
- Xend DevController.createDevice() check verify this node and return success
or throw an exception on failure.
- If no changes in "hotplug-status" node after DEVICE_CREATE_TIMEOUT seconds
Xend throw an exception showing the problem with hotplug scripts.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
tools/examples/block-common.sh
tools/examples/vif-bridge
tools/examples/vif-nat
tools/examples/vif-route
tools/examples/xen-hotplug-common.sh
tools/python/xen/xend/server/DevController.py

index 1d20550a9da541462a5e21a1a88e116dccc69210..397f588c71de42ea353bc57cedf64539ae1ea85b 100644 (file)
@@ -42,10 +42,17 @@ write_dev() {
   local major
   local minor
   local pdev
-       
+  
   major=$(stat -L -c %t "$1")
   minor=$(stat -L -c %T "$1")
+  if [ -z $major  -o -z $minor ]; then
+    fatal "Backend device does not exist"
+  fi
   pdev=$(printf "0x%02x%02x" "0x$major" "0x$minor")
   xenstore_write "$XENBUS_PATH"/physical-device "$pdev" \
                  "$XENBUS_PATH"/node "$1"
+
+  success
 }
index 4ba683c25caf7666cfefdb7e476d144a317784cc..d95d8ecef56b35341baea0af42e0c4da944facaa 100755 (executable)
@@ -58,6 +58,7 @@ case "$command" in
           fatal "brctl addif $bridge $vif failed"
 
         ifconfig "$vif" up || fatal "ifconfig $vif up failed"
+        success
         ;;
     down)
         # vifs are auto-removed from bridge.
index bf9f40a7b98c0b1c7a495b7c79aee5996fcb48be..2d751edc60d787d5309f34251c3f9ae507f41b03 100644 (file)
@@ -54,3 +54,5 @@ esac
 ip r ${ipcmd} ${ip} dev ${vif} src ${main_ip}
 
 handle_iptable()
+
+success
index beb8e43ef212cfc4adfa5b45fc7f91135be29701..c804a01840c34ef18f2a21fddf40a887ef14ce71 100755 (executable)
@@ -46,3 +46,5 @@ if [ "${ip}" ] ; then
 fi
 
 handle_iptable()
+
+success
index cc5af864a28af9fcbee598264063394ca4194d50..9cce5175a21917bd59e74b12a797ac513269b2f4 100644 (file)
@@ -30,10 +30,16 @@ log() {
 }
 
 fatal() {
+  xenstore_write "$XENBUS_PATH"/hotplug-status error
   log err "$@"
   exit 1
 }
 
+success() {
+  # Tell DevController that backend is "connected"
+  xenstore_write "$XENBUS_PATH"/hotplug-status connected
+}
+
 ##
 # xenstore_read <path>+
 #
index fdc0404235819bdd32609e6ae70dda8cf4cc73f5..83363f9281e6218c76ab2cbb3411881b19c8de95 100644 (file)
 # Copyright (C) 2005 XenSource Ltd
 #============================================================================
 
+from threading import Event
 
 from xen.xend import sxp
 from xen.xend.XendError import VmError
 from xen.xend.XendLogging import log
+
 from xen.xend.xenstore.xstransact import xstransact
+from xen.xend.xenstore.xswatch import xswatch
 
+DEVICE_CREATE_TIMEOUT = 120
+HOTPLUG_STATUS_NODE = "hotplug-status"
+HOTPLUG_STATUS_ERROR = "error"
 
 class DevController:
     """Abstract base class for a device controller.  Device controllers create
@@ -54,6 +60,18 @@ class DevController:
 
         self.writeDetails(config, devid, back, front)
 
+        status, fn_ret = self.waitForBackend(devid)
+        if status:
+            self.destroyDevice(devid)
+            raise VmError( ("Device %s (%s) could not be connected. "
+                            "Hotplug scripts not working") 
+                            % (devid, self.deviceClass))
+
+        elif fn_ret == HOTPLUG_STATUS_ERROR:
+            self.destroyDevice(devid)
+            raise VmError( ("Device %s (%s) could not be connected. "
+                            "Backend device not found!") 
+                            % (devid, self.deviceClass))
         return devid
 
 
@@ -242,6 +260,29 @@ class DevController:
         xstransact.Write(frontpath, frontDetails)
         xstransact.Write(backpath, backDetails)
 
+    def waitForBackend(self,devid):
+        ev = Event()
+
+        def hotplugStatus():
+            status = self.readBackend(devid, HOTPLUG_STATUS_NODE)
+            if status is not None:
+                watch.xs.unwatch(backpath, watch)
+                hotplugStatus.value = status
+                ev.set()
+
+        hotplugStatus.value = None
+        frontpath = self.frontendPath(devid)
+        backpath = xstransact.Read(frontpath, "backend")
+
+        watch = xswatch(backpath, hotplugStatus)
+
+        ev.wait(DEVICE_CREATE_TIMEOUT)
+        if ev.isSet():
+            return (0, hotplugStatus.value)
+        else:
+            return (-1, hotplugStatus.value)
+
+
 
     def backendPath(self, backdom, devid):
         """@param backdom [XendDomainInfo] The backend domain info."""